package Window;
import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW;
import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import BrickControlGuide.BrickMovementGuideRenderer;
import Builder.AutoSaveManager;
import Builder.BrickSelectionManager;
import Builder.BuilderConfigurationManager;
import Builder.ConnectivityRendererForBrickViewer;
import Builder.DragSelectionInfoRenderer;
import Builder.MainCamera;
import Builder.MetaInfoRenderer;
import Command.LDrawPart;
import Common.Size2;
import Common.Vector3f;
import Connectivity.ConnectivityTestResultT;
import Connectivity.GlobalConnectivityManager;
import Connectivity.GlobalConnectivityRenderer;
import LDraw.Support.LDrawGLRenderer;
import LDraw.Support.MatrixMath;
import Notification.ILDrawSubscriber;
import Notification.INotificationMessage;
import Notification.NotificationCenter;
import Notification.NotificationMessageT;
import Resource.ResourceManager;
import Resource.SoundEffectManager;
import Resource.SoundEffectT;
import UndoRedo.DirectiveAction;
import UndoRedo.LDrawUndoRedoManager;
import com.jogamp.opengl.swt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
public class MOCBuilderUI implements GLEventListener, ILDrawSubscriber {
FPSAnimator animator;
LDrawGLRenderer glRenderer;
MetaInfoRenderer metaInfoRenderer;
BrickMovementGuideRenderer brickMovementGuideRenderer;
GlobalConnectivityRenderer connectivityRenderer;
PartBrowserUI browserUI;
GroupEditorView groupEditorView;
// FileInfoUI fileInfoUI;
GLCanvas glcanvas;
MainCamera camera;
MOCBuilder mocBuilder = null;
DragSelectionInfoRenderer brickSelectionInfoRenderer;
GlobalBoundingBoxRenderer boundingBoxRenderer;
Shell shell;
SashForm sashForm;
Composite mainView;
ToolBarHandler toolbar;
public MOCBuilderUI(MOCBuilder builder) {
this.mocBuilder = builder;
}
public void open(Display display) {
shell = new Shell(display);
mocBuilder.setShell(shell);
BuilderConfigurationManager configurationManager = BuilderConfigurationManager
.getInstance();
shell.setText(MOCBuilder.APP_NAME);
shell.setSize((int) configurationManager.getWindowSize().getWidth(),
(int) configurationManager.getWindowSize().getHeight());
shell.setLocation(new Point((int) configurationManager
.getWindowPosition().getX(), (int) configurationManager
.getWindowPosition().getY()));
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent event) {
if (!mocBuilder.checkChanged(shell)) {
event.doit = false;
}
super.shellClosed(event);
}
});
shell.setImage(ResourceManager.getInstance().getImage(display,
"/Resource/Image/bl_new_icon.png"));
shell.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent arg0) {
if (shell.getMaximized() || shell.getMinimized())
return;
BuilderConfigurationManager.getInstance().setWindowPosition(
shell.getLocation().x, shell.getLocation().y);
BuilderConfigurationManager.getInstance().setWindowSize(
shell.getSize().x, shell.getSize().y);
groupEditorView.terminate();
BackgroundThreadManager.getInstance().terminate();
animator.stop();
AutoSaveManager.getInstance().terminate();
}
});
camera = mocBuilder.getCamera();
// generate window component
generateComposite();
// fileInfoUI = new FileInfoUI(brickBuilder);
// fileInfoUI.open();
shell.open();
GlobalFocusManager.getInstance().forceFocusToMainView();
if (AutoSaveManager.getInstance().isExistAutoSaveFile()) {
MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION
| SWT.YES | SWT.NO);
messageBox.setText("AutoSave");
messageBox
.setMessage("Temperary saved file is existing. \r\n Do you want to load it?");
if (messageBox.open() == SWT.YES) {
AutoSaveManager.getInstance().loadAutoSavedFile();
}
}
AutoSaveManager.getInstance().start();
// brickBuilder.openFile("j:/connectivity Test.ldr");
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
BuilderConfigurationManager.getInstance().updateFile();
browserUI.close();
groupEditorView.terminate();
AutoSaveManager.getInstance().terminate();
shell.dispose();
display.dispose();
}
private void generateComposite() {
GridLayout gridlayout = new GridLayout();
gridlayout.numColumns = 1;
gridlayout.marginTop = 0;
gridlayout.marginBottom = 0;
gridlayout.marginHeight = 0;
shell.setLayout(gridlayout);
// Menu bar
new MenuHandler(mocBuilder, shell).generateMenu();
// Toolbar
toolbar = new ToolBarHandler(mocBuilder, shell);
toolbar.generateToolbar();
sashForm = new SashForm(shell, SWT.HORIZONTAL);
sashForm.setLocation(10, 40);
sashForm.setSashWidth(3);
sashForm.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
| GridData.FILL_VERTICAL));
browserUI = new PartBrowserUI(sashForm, SWT.NONE);
mainView = new Composite(sashForm, SWT.BORDER);
mainView.setLayout(new FillLayout());
mainView.setBounds(10, 40, 728, 519);
GLProfile glprofile = GLProfile.getDefault();
GLCapabilities glcapabilities = new GLCapabilities(glprofile);
glcanvas = new GLCanvas(mainView, SWT.NO_BACKGROUND, glcapabilities,
null);
initEventListener();
animator = new FPSAnimator(glcanvas, 30);
GlobalFocusManager.getInstance(mainView);
// right panel
Composite rightPanel = new Composite(sashForm, SWT.BORDER);
rightPanel.setLayout(new GridLayout());
rightPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
SashForm sashForm2 = new SashForm(rightPanel, SWT.NONE);
sashForm2.setOrientation(SWT.VERTICAL);
sashForm2.setLayout(new GridLayout());
sashForm2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// ModelListView
ModelListView modelListView = new ModelListView(sashForm2, SWT.NONE);
// GroupEditor
groupEditorView = new GroupEditorView(mocBuilder);
groupEditorView.generateView(sashForm2);
sashForm2.setWeights(new int[] { 1, 4 });
sashForm.setWeights(BuilderConfigurationManager.getInstance()
.getSashDivision());
sashForm.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent arg0) {
BuilderConfigurationManager.getInstance().setSashDivision(
((SashForm) arg0.getSource()).getWeights());
}
});
setDragTarget(mainView);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
StatusBar statusBar = new StatusBar(shell, SWT.BORDER, mocBuilder);
statusBar.setLayoutData(gridData);
}
public void setDragTarget(Control control) {
final TextTransfer textTransfer = TextTransfer.getInstance();
final FileTransfer fileTransfer = FileTransfer.getInstance();
DropTarget target = new DropTarget(control, DND.DROP_COPY
| DND.DROP_MOVE | DND.DROP_DEFAULT);
target.setTransfer(new Transfer[] { fileTransfer, textTransfer });
target.addDropListener(new DropTargetListener() {
LDrawPart part;
@Override
public void dropAccept(DropTargetEvent event) {
}
@Override
public void drop(DropTargetEvent event) {
mocBuilder.getMetaInfoRenderer().setShowBaseplate(
BuilderConfigurationManager.getInstance()
.isUseDefaultBaseplate());
if (part == null) {
Object object = event.data;
if (object != null) {
if (fileTransfer.isSupportedType(event.currentDataType)) {
String[] filePaths = (String[]) object;
for (String path : filePaths) {
if (path.toLowerCase().endsWith(".ldr")
|| path.toLowerCase().endsWith(".mpd")
|| path.toLowerCase().endsWith(".dat")) {
Point coordinates = mainView
.toControl(new Point(event.x,
event.y));
Vector3f pos = camera.screenToWorldXZ(
coordinates.x, coordinates.y, 0);
mocBuilder.importFile(path, pos);
return;
}
if (path.toLowerCase().endsWith(".lxf")
|| path.toLowerCase()
.endsWith(".lxfml")) {
// Point coordinates = mainView
// .toControl(new Point(event.x,
// event.y));
// Vector3f pos = camera.screenToWorldXZ(
// coordinates.x, coordinates.y, 0);
mocBuilder.openFile(path);
return;
}
}
}
}
} else {
if (BuilderConfigurationManager.getInstance()
.isUseConnectivity()
&& GlobalConnectivityManager.getInstance()
.isConnectable(part).getResultType() == ConnectivityTestResultT.False) {
// nothing
if (BuilderConfigurationManager.getInstance()
.isTurnOffSound() == false)
SoundEffectManager.getInstance().playSoundEffect(
SoundEffectT.ConnectingFail);
} else {
mocBuilder.addDirectiveToWorkingFile(part);
BrickSelectionManager.getInstance()
.clearSelection(true);
BrickSelectionManager.getInstance().addPartToSelection(
part);
DirectiveAction action = new DirectiveAction();
action.addDirective(part);
LDrawUndoRedoManager.getInstance().pushUndoAction(
action);
part = null;
if (BuilderConfigurationManager.getInstance()
.isTurnOffSound() == false)
SoundEffectManager.getInstance().playSoundEffect(
SoundEffectT.ConnectingSuccess);
}
}
mainView.setFocus();
}
@Override
public void dragOver(DropTargetEvent event) {
if (part != null) {
Point coordinates = mainView.toControl(new Point(event.x,
event.y));
GlobalMousePosition.getInstance().setPos(coordinates.x,
coordinates.y);
Vector3f hitPos = new Vector3f(mocBuilder.getHittedPos(
coordinates.x, coordinates.y, true));
if (MatrixMath.compareFloat(hitPos.y, 0) == 0)
hitPos = hitPos.add(getPartOffset(part, hitPos));
mocBuilder.moveDirectiveTo(part, hitPos);
}
}
@Override
public void dragOperationChanged(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
if (fileTransfer.isSupportedType(event.currentDataType)) {
if (event.detail != DND.DROP_COPY) {
event.detail = DND.DROP_NONE;
}
}
}
@Override
public void dragLeave(DropTargetEvent event) {
if (part != null) {
removeBrick(part);
}
event.operations = DND.DROP_NONE;
event.detail = DND.DROP_NONE;
}
private void removeBrick(LDrawPart part) {
mocBuilder.removeDirectiveFromWorkingFile(part, true);
brickMovementGuideRenderer.setLDrawPart(null);
}
private void addBrick(String partName, DropTargetEvent event) {
Point coordinates = mainView.toControl(new Point(event.x,
event.y));
Vector3f pos = camera.screenToWorldXZ(coordinates.x,
coordinates.y, 0);
part = new LDrawPart();
part.initWithPartName(partName, pos);
part.setLDrawColor(DNDTransfer.getInstance().getColor());
// part.getConnectivityList();
mocBuilder.addDirectiveToWorkingFileForDragAndDrop(part);
BrickSelectionManager.getInstance().clearSelection();
}
@Override
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
for (TransferData data : event.dataTypes) {
if (fileTransfer.isSupportedType(data)) {
event.currentDataType = data;
if (event.detail != DND.DROP_COPY) {
event.detail = DND.DROP_NONE;
}
return;
}
}
if (textTransfer.isSupportedType(event.currentDataType)) {
Object object = DNDTransfer.getInstance().getData();
if (object != null) {
String partName = object.toString();
if (browserUI.contains(partName)) {
addBrick(partName, event);
BrickSelectionManager.getInstance()
.addPartToSelection(part);
if (part.getConnectivityMatrixItemList() == null)
mocBuilder.getMetaInfoRenderer()
.setShowBaseplate(false);
return;
} else {
if (mocBuilder.getWorkingLDrawFile() != null) {
if (mocBuilder.getWorkingLDrawFile()
.modelNames().contains(partName)) {
addBrick(partName, event);
BrickSelectionManager.getInstance()
.addPartToSelection(part);
if (part.getConnectivityMatrixItemList() == null)
mocBuilder.getMetaInfoRenderer()
.setShowBaseplate(false);
return;
}
}
}
}
event.detail = DND.DROP_NONE;
}
}
});
}
@Override
public void dispose(GLAutoDrawable glautodrawable) {
animator.stop();
}
@Override
public void init(GLAutoDrawable glautodrawable) {
GL2 gl2 = (GL2) glautodrawable.getGL(); // get the OpenGL graphics
gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
// gl2.glBindVertexArray(0);
// init gl related component
glRenderer = mocBuilder.getGLRenderer();
metaInfoRenderer = mocBuilder.getMetaInfoRenderer();
brickMovementGuideRenderer = mocBuilder.getBrickMovementGuideRenderer();
connectivityRenderer = mocBuilder.getConnectivityRenderer();
brickSelectionInfoRenderer = mocBuilder.getBrickSelectionInfoRenderer();
boundingBoxRenderer = GlobalBoundingBoxRenderer.getInstance(camera);
mocBuilder.initGLReleatedComponent(new Size2(800f, 600f), gl2);
// animator.start();
}
ConnectivityRendererForBrickViewer testRenderer = null;
@Override
public void display(GLAutoDrawable glautodrawable) {
GL2 gl2 = (GL2) glautodrawable.getGL(); // get the OpenGL graphics
gl2.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl2.glLoadIdentity(); // Reset The Modelview Matrix
camera.tickle();
try {
metaInfoRenderer.draw(gl2);
} catch (Exception e) {
e.printStackTrace();
}
// long t = System.nanoTime();
try {
glRenderer.draw(gl2);
} catch (Exception e) {
e.printStackTrace();
}
// System.out.println((System.nanoTime()-t));
try {
brickMovementGuideRenderer.draw(gl2);
} catch (Exception e) {
e.printStackTrace();
}
try {
connectivityRenderer.draw(gl2);
} catch (Exception e) {
e.printStackTrace();
}
try {
brickSelectionInfoRenderer.draw(gl2);
boundingBoxRenderer.draw(gl2);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void reshape(GLAutoDrawable glautodrawable, int x, int y, int width,
int height) {
GL2 gl = (GL2) glautodrawable.getGL(); // get the OpenGL graphics
// context
if (height == 0)
height = 1; // prevent divide by zero
camera.setScreenSize(width, height);
BrickSelectionManager.getInstance()
.updateScreenProjectionVerticesMapAll();
// Set the view port (display area) to cover the entire window
gl.glViewport(0, 0, width, height);
// Setup perspective projection, with aspect ratio matches viewport
gl.glMatrixMode(GL_PROJECTION); // choose projection matrix
gl.glLoadIdentity(); // reset projection matrix
// Enable the model-view transform
gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity(); // reset
gl.glEnable(GL2.GL_BLEND);
gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
brickSelectionInfoRenderer.setCanvasSize(width, height);
}
private void initEventListener() {
BuilderEventHandler eventHandler = new BuilderEventHandler(mocBuilder);
glcanvas.addMouseListener(eventHandler);
glcanvas.addMouseMoveListener(eventHandler);
glcanvas.addMouseWheelListener(eventHandler);
glcanvas.addMouseTrackListener(eventHandler);
// init keyboard event handler for test
glcanvas.addKeyListener(eventHandler);
glcanvas.addKeyListener(toolbar);
glcanvas.addGLEventListener(this);
mainView.addKeyListener(eventHandler);
mainView.addMouseWheelListener(eventHandler);
EventHandlerForCursor cursorEventHandler = new EventHandlerForCursor(
mainView);
glcanvas.addKeyListener(cursorEventHandler);
glcanvas.addMouseMoveListener(cursorEventHandler);
mainView.addKeyListener(cursorEventHandler);
mainView.addMouseMoveListener(cursorEventHandler);
NotificationCenter.getInstance().addSubscriber(this,
NotificationMessageT.NeedReDraw);
new Thread(new Runnable() {
@Override
public void run() {
while (shell.isDisposed() == false) {
if (needRedraw) {
needRedraw = false;
glcanvas.display();
} else
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
private boolean needRedraw = false;
@Override
public void receiveNotification(NotificationMessageT messageType,
INotificationMessage msg) {
needRedraw = true;
}
private Vector3f getPartOffset(LDrawPart part, Vector3f hitWorldPos) {
Vector3f retValue = null;
Vector3f veye = new Vector3f(0, 0,
camera.getDistanceBetweenObjectToCamera());
veye = camera.getModelViewMatrix().multiply(veye);
veye = camera.getLookAtPos().add(veye);
float y_hitted = part.boundingBox3(part.getRotationMatrix()).getMax().y;
y_hitted *= -1.0f;
double tanThetaX = veye.y / (veye.x - hitWorldPos.x);
double tanThetaZ = veye.y / (veye.z - hitWorldPos.z);
double offsetX = y_hitted / tanThetaX;
double offsetZ = y_hitted / tanThetaZ;
retValue = new Vector3f((float) offsetX, y_hitted, (float) offsetZ);
return retValue;
}
}